package com.qdd.freight.handler.impl;

import com.alibaba.fastjson.JSON;
import com.qdd.freight.anno.Mode;
import com.qdd.freight.entity.Datas;
import com.qdd.freight.entity.deppon.PriceInfo;
import com.qdd.freight.entity.deppon.QueryPriceRequest;
import com.qdd.freight.entity.deppon.StandardResultInfo;
import com.qdd.freight.exception.FreightToBeZeroExcption;
import com.qdd.freight.exception.NoShipFoundException;
import com.qdd.freight.handler.AbstractLogisticsHandler;
import com.qdd.freight.pojo.GoodsShip;
import com.qdd.freight.pojo.Logistics;
import com.qdd.freight.util.FastJsonUtil;
import com.qdd.freight.util.HttpClientUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 德邦物流-网点自提
 *
 * @ClassName NormalLogisticsHandler
 * @Description TODO
 * @Author yanpeihao
 * @Date 2019/12/6 22:47
 * @Version 2.2
 **/
@Component
@Mode("4")
public class DBLogZTHandler extends AbstractLogisticsHandler {

    /**
     * 关键属性值，避免使用时再查询数据库中的字段
     */
    //运输类型,1:物流运输,2:整车运输
    private static final Integer CARRIER_TYPE = 1;
    //承运商类别，1:普通物流,2:京东快运,3:德邦物流
    private static final Integer TRANSPORT = 3;
    //配送类型,1:物流自提,2:送货上门
    private static final Integer DELIVER_YTYPE = 1;
    //快运方式名称：默认的应该需对应页面的名称
    private static final String YFMODE_NAME = "德邦物流";
    //对应数据库的字段名
//    private static final String TABLE_FIELD_NAME = "dbwl_id" ;
//    //对应数据库的字段名
    private static final String CONSTANT_FIELD_NAME = "dbwlId";

    @Override
    public String getShipFieldNameFromInstance() {
        return CONSTANT_FIELD_NAME;
    }

    /**
     * 关键属性值，避免使用时再查询数据库中的字段
     */
    @Override
    public Datas realHandle(GoodsShip goodsShip, Integer shipId, Integer modeId, Integer goodsId,
                            Integer entId, Integer quantity, Integer company, String consignee,
                            Double boxVolume, Double singleVolume, Double boxWeight, Double singleWeight,
                            Integer QTYRate) throws Exception {
        System.out.println("============正在执行处理器计算逻辑....关键信息打印===============");
        System.out.println("承运方式：type:" + YFMODE_NAME);
        System.out.println("承运商：carrierType:" + String.valueOf(Integer.valueOf(CARRIER_TYPE)));
        System.out.println("运输类型:transport" + String.valueOf(Integer.valueOf(TRANSPORT)));
        System.out.println("配送方式：deliveryType:" + String.valueOf(Integer.valueOf(DELIVER_YTYPE)));
        System.out.println("===========准备调用德邦接口==============");
        /*
            1.获取物流对象并判断
         */
        Logistics logistics = getLogistics(shipId);
        if (null == logistics) {
            throw new NoShipFoundException("物流编号：" + shipId + "，未匹配到对应的物流数据！");
        }
        /*
            2.封装请求数据
         */
        //1.设置请求url
        String url = "http://dpapi.deppon.com/dop-interface-sync/standard-query/queryPrice.action";

        //2.设置13位Unix时间戳timestamp
        String timestamp = String.valueOf(System.currentTimeMillis());

        //3.设置AppKey
        String appkey = "55d211be095267038fd3ee9434625a5e";
        String companyCode = "JINANDAOMIN";
//        String sign = "JNDM";

        //4.设置请求参数params
        //获取仓库编码
        String repositoryIds = consignee.split("-")[0];
        String destProvince = repositoryIds.split("_")[0];
        String destCity = repositoryIds.split("_")[1];
        String destDistrict = repositoryIds.split("_")[2];
        //获取收货方地址编码
        String consigneeIds = consignee.split("-")[1];
        String originalProvince = consigneeIds.split("_")[0];
        String originalCity = consigneeIds.split("_")[1];
        String originalDistrict = consigneeIds.split("_")[2];
        QueryPriceRequest request = new QueryPriceRequest();
        request.setDestProvince(destProvince);
        request.setDestCity(destCity);
        request.setDestDistrict(destDistrict);
        request.setLogisticCompanyID("DEPPON");
        request.setOriginalProvince(originalProvince);
        request.setOriginalCity(originalCity);
        request.setOriginalDistrict(originalDistrict);
        String params = FastJsonUtil.toJSONString(request);

        //5.设置base64编码的摘要degis
        String digest = getDigest(params + appkey + timestamp);//注意传递的timestamp要和加密的timestamp值相同。
        //5.封装指定格式的请求数据
        List<NameValuePair> nameValuePairList = new ArrayList<>();
        nameValuePairList.add(new BasicNameValuePair("companyCode", companyCode));
        nameValuePairList.add(new BasicNameValuePair("digest", digest));
        nameValuePairList.add(new BasicNameValuePair("timestamp", timestamp));
        nameValuePairList.add(new BasicNameValuePair("params", params));

        //6.发送post请求
        String responseJson = HttpClientUtils.post(url, nameValuePairList);
        //转换为Content-type=application/x-www-form-urlencoded;格式数据
        System.out.println(responseJson);

        //7.封装返回结果
        StandardResultInfo resultInfo = JSON.parseObject(responseJson, StandardResultInfo.class);
        System.out.println(resultInfo);
        //8.找出可用的计价体系
        List<PriceInfo> priceInfoList = resultInfo.getResponseParam().getPriceInfo();
        //如果未找到，则报错
        if (priceInfoList == null || priceInfoList.size() == 0) {
            throw new FreightToBeZeroExcption("该地区未找到对应的运输方式！");
        }
        //找出指定的计价体系信息，QC_JZQYD优先于QC_JZQYC
        PriceInfo enabledPriceInfo = priceInfoList.stream()
                .filter(item -> "QC_JZQYD".equals(item.getProductCode()) || "QC_JZQYC".equals(item.getProductCode()))
                .findFirst().get();
        //9.进行运费计算 --- 计体积或计重量两种方式的价格，取最大值
        //重量计价方式下的总运费
        BigDecimal heavyRate = enabledPriceInfo.getHeavyRate();
        Double freightByWeight = countFreightByWeightOrVolume(heavyRate, quantity, boxWeight, singleWeight, QTYRate);
        //体积计价方式下的总运费
        BigDecimal lightRate = enabledPriceInfo.getLightRate();
        Double freightByVolume = countFreightByWeightOrVolume(lightRate, quantity, boxVolume, singleVolume, QTYRate);
        //公式：  德邦总价格/1000 * 0.65（折扣率） + 18运费险
        Double totalFreight = ((freightByWeight > freightByVolume) ? freightByWeight : freightByVolume) * 0.001 * 0.65 + 18;

        //看是否大于48元的起步价
        double freight = totalFreight > 48 ? totalFreight : 48;

        //封装结果并返回
        return packageDatas(modeId, goodsId, entId, quantity, freight);
    }

    /**
     * 内部方法
     * 根据体积或重量计算总运费
     *
     * @param heavyOrLightRate     重量或体积费率
     * @param quantity             采购数量
     * @param boxVolumeOrWeight
     * @param singleVolumeOrWeight
     * @param QTYRate
     * @return
     */
    private Double countFreightByWeightOrVolume(BigDecimal heavyOrLightRate, Integer quantity, Double boxVolumeOrWeight,
                                                Double singleVolumeOrWeight, Integer QTYRate) {
        //调用父类方法，计算总重量
        Double totalWeight = getTotalWeightOrVolume(quantity, boxVolumeOrWeight, singleVolumeOrWeight, QTYRate);
        double freightByWeight = new BigDecimal(totalWeight).multiply(heavyOrLightRate).doubleValue();
        return Math.ceil(freightByWeight);
    }


    /**
     * 生成摘要
     * 注意传递的timestamp要和加密的timestamp值相同。
     *
     * @param plainText
     * @return
     */
    private static String getDigest(String plainText) {
        //Base64.getEncoder().encodeToString(plainText.getBytes())；发送json字符串时使用
        return Base64.encodeBase64String(DigestUtils.md5Hex(plainText).getBytes());
    }

}
